<!--
 * @Author: mhb
 * @Date: 2021-09-28 20:20:39
 * @LastEditTime: 2022-06-08 11:46:37
 * @LastEditors: liyuxiao 1273661256@qq.com
 * @Description: 实测实量地图点位操作区域
 * @FilePath: \cscec-pms-admin\src\views\quality\measuredAmount\map\components\Content.vue
-->
<template>
  <a-col :span="16">
    <a-card :bordered="false" style="margin: 0">
      <!-- 头部操作栏 -->
      <a-row class="mb12" type="flex" justify="space-between" align="middle" style="flex-wrap: nowrap; width: 100%">
        <a-col :span="20">
          <a-row type="flex" align="middle" style="flex-wrap: nowrap; width: 100%">
            <!-- 责任区域选中树节点名称 -->
            <title-name :title="nodeTitle" style="margin: 0; flex-shrink: 0"></title-name>
            <!-- 查看模式时显示筛选操作栏 -->
            <template v-if="!!isView">
              <!-- 点位类型 -->
              <a-select
                placeholder="请选择测量层级"
                :allowClear="true"
                style="width: 300px"
                class="ml12"
                v-model="queryParams.leaderFlag"
              >
                <a-icon v-if="leaderFlagLoading" slot="suffixIcon" style="color: #096dd9" type="loading" />
                <a-spin v-if="leaderFlagLoading" slot="notFoundContent" size="small" />
                <a-select-option v-for="item in leaderFlagList" :value="item.code" :key="item.id">
                  {{ item.name }}
                </a-select-option>
              </a-select>
              <!-- 点位类型 -->
              <a-select
                placeholder="请选择测量结果"
                :allowClear="true"
                style="width: 300px"
                class="ml12"
                v-model="queryParams.measurementResult"
              >
                <a-select-option v-for="item in measurementResults" :value="item.id" :key="item.id">
                  {{ item.name }}
                </a-select-option>
              </a-select>
              <!-- 点位名称 -->
              <a-select
                placeholder="请选择点位名称"
                :allowClear="true"
                style="width: 300px"
                class="ml12"
                v-model="queryParams.pointTypeId"
              >
                <a-icon v-if="downLoading" slot="suffixIcon" style="color: #096dd9" type="loading" />
                <a-spin v-if="downLoading" slot="notFoundContent" size="small" />
                <a-select-option v-for="item in pointTypes" :value="item.id" :key="item.id">
                  {{ item.pointName }}
                </a-select-option>
              </a-select>
              <!-- 搜索操作 -->
              <a-button
                class="ml12"
                icon="search"
                style="flex-shrink: 0"
                :disabled="!selectedKeys.length"
                type="primary"
                @click="$emit('handleSearch')"
                >筛选</a-button
              >
              <a-button
                class="ml12"
                :disabled="!selectedKeys.length"
                style="flex-shrink: 0"
                type="primary"
                icon="reload"
                @click="
                  queryParams.measurementResult = void 0
                  queryParams.pointTypeId = void 0
                  queryParams.leaderFlag = void 0
                  $emit('handleSearch')
                "
                >重置</a-button
              >
            </template>
          </a-row>
        </a-col>
        <!-- 导出操作栏 -->
        <a-col :span="3">
          <div align="right" v-btnPermission="'qm_010_add_03'">
            <a-dropdown :disabled="!projectImg" v-if="!!isView" placement="topCenter">
              <a-button type="primary">导出<a-icon type="down" /></a-button>
              <a-menu slot="overlay">
                <!-- 导出点位信息 -->
                <a-menu-item>
                  <a @click.stop="exportPointInfo">导出实测实量记录</a>
                  <!-- 点位信息模板（隐藏） -->
                  <PointInfoTemplate
                    v-show="false"
                    ref="pointInfoTemplate"
                    :picture="picture"
                    :datas="datas"
                    :nodeTitle="nodeTitle"
                  />
                </a-menu-item>
                <!-- 导出二维码 -->
                <a-menu-item :disabled="qrCodeLoading">
                  <a @click.stop="exportQrCode"
                    >导出二维码<a-icon class="ml12" v-show="qrCodeLoading" type="loading"
                  /></a>
                </a-menu-item>
                <!-- 导出地图 -->
                <a-menu-item>
                  <a @click.stop="$refs.point && $refs.point.exportCanvas(selectOptions.name)">导出地图</a>
                </a-menu-item>
              </a-menu>
            </a-dropdown>
            <a-button v-else :disabled="!projectImg" type="primary" icon="plus" @click="$emit('handleManage', 0)"
              >添加测量点位</a-button
            >
          </div>
        </a-col>
      </a-row>
      <!-- 施工图 -->
      <a-card style="box-shadow: none" :bordered="false">
        <a-spin :spinning="loading">
        <div :style="'height: calc('+GET_REDRESS_PERCENTAGE+'vh - 168px)'">
          <Points
            :showMessage="!isView"
            ref="point"
            v-if="!!projectImg"
            :detail.sync="detail"
            :otherAction="isView ? '查看二维码' : ''"
            :img="projectImg"
            :pointerActiveColor="!isView ? '#ff4d4f' : '#037EB4'"
            :isEdit="Object.keys(pointConfig).length > 0 && !isView"
            @remove="handleAction"
            @create="handleAdd"
            :needPicture="true"
            :picture.sync="picture"
            :pointer.sync="pointer"
          />
          <empty v-else description="暂未上传施工图" />

        </div>
      </a-spin>
      </a-card>
      <div class="point-info" v-if="!!projectImg">
        <div class="point-info-title">说明：</div>
        <div class="point-info-item">
          <div class="point-info-circle point-info-circle1"></div>
          <div class="point-info-txt">公司测量</div>
        </div>
        <div class="point-info-item">
          <div class="point-info-circle point-info-circle2"></div>
          <div class="point-info-txt">分公司测量</div>
        </div>
        <div class="point-info-item">
          <div class="point-info-circle point-info-circle3"></div>
          <div class="point-info-txt">项目测量</div>
        </div>
        <div class="point-info-item">
          <div class="point-info-circle point-info-circle4"></div>
          <div class="point-info-txt">不合格点位</div>
        </div>
        <div class="point-info-item">
          <div class="point-info-circle point-info-circle5"></div>
          <div class="point-info-txt">合格点位</div>
        </div>
        <div class="point-info-item">
          <div class="point-info-circle point-info-circle6"></div>
          <div class="point-info-txt">未测量点位</div>
        </div>
      </div>
      <div class="point-info" v-else>
      </div>
    </a-card>

    <!-- 添加点位弹窗 -->
    <dialog-choose
      ref="dialogChoose"
      :visible.sync="visible"
      :record.sync="pointConfig"
      :editModel="editModel"
      :form="record"
      :width="1200"
      headerTitle="添加测量点位"
    ></dialog-choose>
    <!-- 二维码查看 -->
    <a-modal :footer="null" @cancel="visibleQrCode = false" :width="520" :visible="visibleQrCode" :title="qrTitle + '二维码'">
      <div class="qrCode-container">
        <VueQrcode :value="qrCode" :options="{ width: 250 }" style="position: absolute;top: 200px;left: calc(50% - 125px);"></VueQrcode>
      </div>
    </a-modal>
  </a-col>
</template>
<script>
import { Empty } from 'ant-design-vue' // 无数据提示
import Points from '@/components/canvas/Points' // 点位控制图
import DialogChoose from '@/views/quality/measuredAmount/map/components/DialogChoose.vue' // 选择测量点位
import PointInfoTemplate from '@/views/quality/measuredAmount/map/components/PointInfoTemplate.vue' // 点位详情模板
import QRCode from 'qrcodejs2' // 二维码
import FileSaver from 'file-saver'
import JSZip from 'jszip'
import VueQrcode from '@chenfengyuan/vue-qrcode'
import { saveAs } from 'file-saver'
import { qualityTypeLabel } from '@/api/quality/projectDivision' // api
import {mapGetters } from 'vuex'
export default {
  name: 'MapContent',
  components: {
    Empty,
    DialogChoose,
    PointInfoTemplate,
    VueQrcode,
    Points
  },
  props: {
    // 通用请求api
    api: {
      type: [Function, Object, Promise]
    },
    // 操作类型：0 添加 1 编辑 3 查看
    editModel: {
      type: [Number, String],
      default: () => '0'
    },
    // 选中点位坐标对象
    details: {
      type: Object,
      default: () => ({})
    },
    // 点位坐标列表
    pointList: {
      type: Array,
      default: () => []
    },
    // 选中节点对象
    selectOptions: {
      type: Object,
      default: () => ({})
    },
    // 详情请求参数
    queryParams: {
      type: Object,
      default: () => ({})
    },
    // 点位信息加载控件
    loading: {
      type: Boolean,
      default: () => false
    },
    // 施工图
    projectImg: {
      type: String,
      default: () => ''
    },
    // 责任区域详情对象
    datas: {
      type: Object,
      default: () => ({})
    },
    // 点位坐标列表
    points: {
      type: Array,
      default: () => []
    },
    // 选中点位
    point: {
      type: Array,
      default: () => []
    },
    // 选中树节点
    selectedKeys: {
      type: Array,
      default: () => []
    }
  },
  mounted() {
    this.record = {
      id: this.id,
      projectId: this.projectId
    }
  },
  data() {
    return {
      measurementResults: [
        {
          id: 0,
          name: '已测'
        },
        {
          id: 1,
          name: '未测'
        },
        {
          id: 2,
          name: '合格'
        },
        {
          id: 3,
          name: '不合格'
        }
      ], // 点位类型
      leaderFlagLoading: false,
      leaderFlagList: [],
      qrCodeLoading: false, // 导出二维码loading
      visibleQrCode: false, // 二维码弹窗控件
      qrCode: '', // 二维码链接
      pointTypes: [], // 点位名称列表
      qrTitle: '', // 二维码标题
      qrCodes: [], // 二维码集合
      downLoading: false, // 点位名称请求loading
      projectId: this.$route.query.projectId, // 项目id
      isView: this.$route.query.isView, // 是否为查看操作
      id: this.$route.query.id, // 业务id
      record: {}, // 点位详情
      pointConfig: {}, // 测量点点位配置
      visible: false, // 责任区域弹窗控件
      picture: '' // 点位图
    }
  },
  // watch: {
  //   // 监听施工图重新生成点位图
  //   projectImg(e) {
  //     setTimeout(() => {
  //       console.log(e, this.$refs)
  //       if (e && this.$refs.point) {
  //         this.picture = this.$refs.point.generatePic()
  //         console.log(this.picture)
  //       }
  //     },800)
  //   }
  // },
  computed: {
    ...mapGetters(['GET_REDRESS_PERCENTAGE']),
    // 节点标题
    nodeTitle() {
      let title = this.selectOptions.name || '请选择区域'
      return title
    },
    // 选中节点
    activePoint: {
      get: function () {
        return this.point
      },
      set: function (e) {
        this.$emit('update:point', e)
      }
    },
    // 选中节点对象
    detail: {
      get: function () {
        return this.details
      },
      set: function (e) {
        this.$emit('update:details', e)
      }
    },
    // 点位坐标列表
    pointer: {
      get: function () {
        return this.points
      },
      set: function (e) {
        this.$emit('update:points', e)
      }
    }
  },
  methods: {
    /**
     * @description: 导出点位信息（参考jquery.wordexport.js源码)
     */
    exportPointInfo() {
      let fileName = this.selectOptions.name
      /**
       * jquery.wordexport.js源码——START
       */
      var statics = {
        mhtml: {
          top:
            'Mime-Version: 1.0\nContent-Base: ' +
            location.href +
            '\nContent-Type: Multipart/related; boundary="NEXT.ITEM-BOUNDARY";type="text/html"\n\n--NEXT.ITEM-BOUNDARY\nContent-Type: text/html; charset="utf-8"\nContent-Location: ' +
            location.href +
            '\n\n<!DOCTYPE html>\n<html>\n_html_</html>',
          head: '<head>\n<meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n<style>\n_styles_\n</style>\n</head>\n',
          body: '<body>_body_</body>'
        }
      }
      var options = {
        maxWidth: 624
      }
      // Embed all images using Data URLs
      var images = Array()
      const inerHTML = this.$refs.pointInfoTemplate.$el.innerHTML
      var img = this.$refs.pointInfoTemplate.$el.getElementsByTagName('img')
      var reg =
        /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@\/?%\s]*?)\s*$/i
      for (var i = 0; i < img.length; i++) {
        let uri
        // 如果是base64格式输出该base64
        if (reg.test(img[i].src)) {
          uri = img[i].src
        } else {
          // Calculate dimensions of output image
          var w = Math.min(img[i].width, options.maxWidth)
          var h = img[i].height * (w / img[i].width)
          // Create canvas for converting image to data URL
          var canvas = document.createElement('CANVAS')
          canvas.width = w
          canvas.height = h
          // Draw image to canvas
          var context = canvas.getContext('2d')
          context.drawImage(img[i], 0, 0, w, h)
          // Get data URL encoding of image
          uri = canvas.toDataURL('image/png/jpg')
          // $(img[i]).attr('src', img[i].src)
          img[i].width = w
          img[i].height = h
        }
        // Save encoded image to array
        images[i] = {
          type: uri.substring(uri.indexOf(':') + 1, uri.indexOf(';')),
          encoding: uri.substring(uri.indexOf(';') + 1, uri.indexOf(',')),
          location: img[i].src,
          data: uri.substring(uri.indexOf(',') + 1)
        }
      }
      var mhtmlBottom = '\n'
      for (var i = 0; i < images.length; i++) {
        mhtmlBottom += '--NEXT.ITEM-BOUNDARY\n'
        mhtmlBottom += 'Content-Location: ' + images[i].location + '\n'
        mhtmlBottom += 'Content-Type: ' + images[i].type + '\n'
        mhtmlBottom += 'Content-Transfer-Encoding: ' + images[i].encoding + '\n\n'
        mhtmlBottom += images[i].data + '\n\n'
      }
      mhtmlBottom += '--NEXT.ITEM-BOUNDARY--'

      var styles = ''
      // Aggregate parts of the file together
      var fileContent =
        statics.mhtml.top.replace(
          '_html_',
          statics.mhtml.head.replace('_styles_', styles) + statics.mhtml.body.replace('_body_', inerHTML)
        ) + mhtmlBottom

      // Create a Blob with the file contents
      var blob = new Blob([fileContent], {
        type: 'application/msword;charset=utf-8'
      })
      saveAs(blob, fileName + '.doc')
    },
    /**
     * @description: base64转文件Blob
     * @param {String} dataurl:base64的url
     * @return {Blob}
     */
    dataURLtoBlob(dataurl) {
      var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      // console.log(mime)
      return new Blob([u8arr], { type: mime })
    },
    /**
     * @description: 导出二维码
     */
    exportQrCode() {
      // 节流防抖
      if (this.qrCodeLoading) {
        return
      }
      if (this.pointList.length) {
        this.qrCodeLoading = true
        let bg = require('@/assets/qrCodeBg.jpg') // 二维码背景图片
        for (let idx in this.pointList) {
          let item = this.pointList[idx]
          const qrcode = document.createElement('div')
          qrcode.innerHTML = ''
          let url = `${location.origin}/quality/measuredAmount/map/pointInfo?type=view&mapId=${this.datas.id}&id=${item.mapId}&areaId=${this.selectedKeys[0]}` // 二维码链接
          // 生成二维码
          new QRCode(qrcode, {
            text: url, //二维码内容
            width: 160, // 二维码宽度
            height: 160, // 二维码高度
            colorDark: '#333333', //二维码颜色
            colorLight: '#fff' //二维码背景色
          })
          // 延迟处理，等二维码dom生成
          setTimeout(() => {
            let qrCodeSrc = qrcode.getElementsByTagName('img')[0].src // 获取dom的二维码的base64链接
            let canvas = document.createElement('canvas') // 新建canvas
            // 固定画布宽度和高度
            canvas.width = 298
            canvas.height = 450
            let ctx = canvas.getContext('2d') // 获取画布2d对象
            let bgImg = new Image() // 二维码背景图对象
            let qrCodeImage = new Image() // 二维码图对象
            // 映射二维码背景图链接
            bgImg.src = bg
            // 映射二维码链接
            qrCodeImage.src = qrCodeSrc
            // 背景图是异步，所以等背景图加载结束再开始绘图
            bgImg.onload = () => {
              // 绘制白色背景
              ctx.fillStyle = '#fff'
              ctx.fillRect(0, 0, 298, 450)
              // 绘制二维码背景图
              ctx.drawImage(bgImg, 0, 0, 298, 355)
              // 绘制二维码
              ctx.drawImage(qrCodeImage, 70, 126, 160, 160)
              // 设置画笔颜色
              ctx.fillStyle = '#054EBF'
              // 设置字体样式
              ctx.font = 'bolder 16px "Times New Roman",Georgia,Serif'
              // 设置字体垂直居中
              ctx.textBaseline = 'middle'
              // 填充文字
              ctx.fillText(`测量区域：${this.selectOptions.name}`, 6, 375)
              ctx.fillText(`点位名称：${item.pointName}`, 6, 405)
              ctx.fillText(`点位编号：${item.serialNumber}`, 6, 435)
              let base64 = canvas.toDataURL('image/jpeg') // 二维码的base64链接
              let dataURLtoBlob = this.dataURLtoBlob(base64) // base64转文件Blob
              // 添加到二维码列表
              this.qrCodes.push({ name: item.name + item.pointName, url: dataURLtoBlob })
              // 当画完最后一个二维码时，把二维码图片列表进行压缩打包
              if (this.qrCodes.length == this.pointList.length) {
                const zip = new JSZip()
                for (let item of this.qrCodes) {
                  zip.file(item.name + '.jpg', item.url, { binary: true }) // 逐个添加文件，需要加后缀".jpg"
                }
                zip.generateAsync({ type: 'blob' }).then((content) => {
                  // 生成二进制流
                  FileSaver.saveAs(content, this.selectOptions.name + '二维码') // 利用file-saver保存文件  自定义文件名
                  // 清除变量缓存
                  qrCodeSrc = null
                  canvas = null
                  ctx = null
                  bgImg = null
                  qrCodeImage = null
                  // 取消加载loading
                  this.qrCodeLoading = false
                  this.$message.success('二维码导出成功！')
                })
              }
            }
          })
        }
      } else {
        this.$message.warning('没有点位可以导出！')
      }
    },
    /**
     * 新添点位
     */
    handleAdd(e) {
      let that = this
      that.pointList.push(
        Object.assign({}, { pointInfo: e, name: `${that.pointList.length + 1}号点位` }, that.$clone(that.pointConfig))
      )
      that.activePoint = [that.pointList.length - 1]
    },
    /**
     * @description: 获取检查类别
     */
     getQualityTypesLabel() {
      this.leaderFlagLoading = true
      // 获取下拉框列表
      qualityTypeLabel({ type: "15" }).then((res) => {
        if (res.data) {
          this.leaderFlagList = res.data;
        }
        this.leaderFlagLoading = false
      }).catch(() => {
        this.leaderFlagLoading = false
      })
    },
    /**
     * @description: 请求点位名称列表
     */
    getPointTypes() {
      this.downLoading = true
      this.api
        ?.down({ respAreaNodeId: this.selectedKeys[0] })
        .then((res) => {
          this.downLoading = false
          if (res.code === 200) {
            this.pointTypes = res.data
          }
        })
        .catch(() => {
          this.downLoading = false
        })
    },
    /**
     * 删除点位或者查看二维码
     */
    handleAction(e) {
      let that = this
      // 删除操作
      if (!that.isView) {
        let sort = false // 删除过后，修改删除点位后面点位序号的标识
        for (let index in that.pointList) {
          let item = that.pointList[index]
          if (item.pointInfo.x === e.x && item.pointInfo.y === e.y) {
            that.pointList.splice(index, 1)
            if (that.pointList[index]) {
              that.pointList[index].name = `${Number(index) + 1}号点位`
            }
            sort = true
          } else if (sort) {
            that.pointList[index].name = `${Number(index) + 1}号点位`
          }
        }
        that.activePoint = [that.pointList.length - 1]
        // 查看二维码操作
      } else {
        that.qrTitle = e.title
        that.qrCode = `${location.origin}/quality/measuredAmount/map/pointInfo?type=view&mapId=${this.datas.id}&id=${e.mapId}&areaId=${this.selectedKeys[0]}`
        that.visibleQrCode = true
      }
    }
  }
}
</script>

<style lang="less" scoped>
.qrCode-container {
  background: url(../../../../../assets/qrCodeBg.jpg) no-repeat top center;
  background-size: cover;
  position: relative;
  height: 562px;
}
.point-info {
  height: 30px;
  display: flex;
  align-items: center;
  font-size: 16px;
  margin: 10px 0;
  padding: 0 10px;
  .point-info-title {
    font-weight: bold;
    max-width: 70px;
    flex: 0 0 70px
  }
  .point-info-item {
    display: inline-flex;
  }
  .point-info-circle {
    width: 24px;
    height: 24px;
    border-radius: 24px;
  }
  .point-info-circle1 {
    background: linear-gradient(to bottom, rgba(99, 0, 191, 1) 0%, rgba(99, 0, 191, 1) 50%, white 51%, white 100%);
  }
  .point-info-circle2 {
    background: linear-gradient(to bottom, rgba(245, 154, 35, 1) 0%, rgba(245, 154, 35, 1) 50%, white 51%, white 100%);
  }
  .point-info-circle3 {
    background: linear-gradient(to bottom, rgba(2, 167, 240, 1) 0%, rgba(2, 167, 240, 1) 50%, white 51%, white 100%);
  }
  .point-info-circle4 {
    background: linear-gradient(to bottom, white 0%, white 50%, rgba(217, 0, 27, 1) 51%, rgba(217, 0, 27, 1) 100%);
  }
  .point-info-circle5 {
    background: linear-gradient(to bottom, white 0%, white 50%, rgba(112, 182, 3, 1) 51%, rgba(112, 182, 3, 1) 100%);
  }
  .point-info-circle6 {
    background: rgba(250, 250, 0, 1);
  }
  .point-info-txt {
    margin-left: 10px;
    margin-right: 20px;
  }
}
</style>